case study_object tracking in video

Object tracking in video


import numpy as np 
import argparse
import time
import cv2 

# construct the argument parse and parse the arguments
ap = argparse.ArgumentParser()
ap.add_argument("-v", "--video",
    help = "path to the (optional) video file")
args = vars(ap.parse_args())

# define the upper and lower boundaries for a color
# to be considered "blue"
blueLower = np.array([100,67,0],dtype="uint8")
blueUpper = np.array([255,128,50],dtype="uint8")

# load the video
if not args.get("video"):
    camera = cv2.VideoCapture(0)
else:
    camera = cv2.VideoCapture(args["video"])

我们将使用NumPy进行数值处理,使用argparse解析命令行参数,使用cv2进行OpenCV绑定。time包是可选的。

我们只需要一个命令行参数,–video,也就是我们视频的路径。

我们将在视频中追踪的对象是蓝色物体。由于除了该物体外,蓝色在视频中的任何其他位置都不常见,因此我们希望跟踪蓝色阴影。为了完成这种颜色跟踪,我们定义了蓝色阴影的下限和上限。请记住,OpenCV表示RGB颜色空间中的像素,但顺序相反。

在这种情况下,如果大于R=0,G=67,B=100且小于R=50,G=128,B=255,则将颜色定义为“蓝色”。

最后,我们打开视频文件并使用cv2.VideoCapture函数获取对它的引用。我们将此引用赋值给变量camera。

# keep looping 
while True:
    # grab the current frame 
    (grabbed,frame) = camera.read()

    # check to see if we have reached the end of the video
    if args.get("video") and not grabbed:
        break 

    # determine which pixels fall within the blue boundaries
    # and then blur the binary image
    blue = cv2.inRange(frame,blueLower,blueUpper)
    blue = cv2.GaussianBlur(blue,(3,3),0)

现在我们有了对视频的引用,便可以开始处理帧。

我们开始循环遍历帧,一次一个。调用read()方法的调用抓取视频中的下一帧,返回具有两个值的元组。第一个是grabbed,是一个布尔值,表示是否从视频文件中成功读取了帧。第二个frame,是帧本身。

然后,我们检查frame是否成功读取。如果未读取框架,则表示已到达视频的末尾,我们break掉while循环。

为了在frame中找到蓝色阴影,我们必须使用cv2.inRange函数。该函数有三个参数。第一个是我们想要检查的frame。第二个是RGB像素的lower threshold,第三个是上限阈值(upper threshold)。调用此函数的结果是阈值图像,像素落在上下范围内设置为白色,像素不属于此范围 设为黑色。

最后,我们对阈值图像进行高斯模糊处理,以使查找轮廓更准确。

    # find contours in the image 
    (_,cnts,_) = cv2.findContours(blue.copy(),cv2.RETR_EXTERNAL,
        cv2.CHAIN_APPROX_SIMPLE)

    # check to see if any contours were found
    if len(cnts) > 0:
        # sort the contours and find the largest one --
        # we will assume this contour coorespondes to the 
        # area of my phone 
        cnt = sorted(cnts,key=cv2.contourArea,reverse=True)[0]

        # compute the (rotated) bounding box around then 
        # contour and then draw it 
        rect = np.int32(cv2.boxPoints(cv2.minAreaRect(cnt)))
        cv2.drawContours(frame,[rect],-1,(0,255,0),2)

    # show the frame and the binary image
    cv2.imshow("Traccking",frame)
    cv2.imshow("Binary",blue)

    # if your machine is fast, it may display the frames in
    # what appears to be 'fast forward' since more than 32
    # frames per second are being displayed -- a simple hack
    # is just to sleep for a tiny bit in between frames;
    # however, if your computer is slow, you probably want to
    # comment out this line
    time.sleep(0.025)

    # if the 'q' key is pressed, stop the loop
    if cv2.waitKey(1) & 0xFF == ord("q"):
        break

# cleanup the camera and close any open windows
camera.release()
cv2.destroyAllWindows()

现在我们有了阈值图像,那么我们需要找到图像中最大的轮廓,假设最大轮廓对应于我们想要跟踪的蓝色物体轮廓。

我们调用cv2.findContours会在阈值图像中找到轮廓。我们使用copy()方法克隆阈值图像,因为cv2.findContour函数对传入的NumPy数组具有破坏性。

然后检查以确保实际发现轮廓。如果轮廓列表的长度为零,则没有找到蓝色区域。如果轮廓列表的长度大于零,那么我们需要找到最大的轮廓。这里,轮廓按相反的顺序排序(最大的第一个),使用cv2.contourArea函数来 计算轮廓的面积。具有较大区域的轮廓存储在列表的前面。在这种情况下,抓住具有最大面积的轮廓,再次假设该轮廓对应于蓝色物体的轮廓。

现在我们有了蓝色的轮廓,但我们需要在它周围绘制一个边界框。

调用cv2.minAreaRect计算轮廓周围的最小边界框。然后,cv2.boxPoints将边界框重新定义为点列表。

注意:在OpenCV 2.4.X中,我们将使用cv2.BoxPoints函数来计算轮廓的旋转边界框。但是,在OpenCV 3.0+中,此函数已移至cv2.boxPoints。两个函数执行相同的任务,只是略有不同的命名空间。

最后,我们使用cv2.drawContours函数绘制边界框。

具有检测到的蓝色物体的frame显示在第一个imshow,并且阈值图像(落入蓝色像素的下/上范围的像素)显示在第二个imshow。

上面,time.sleep(0.025)可选的。在许多较新型号的机器上,系统可能足够快以处理>32帧/秒。如果是这种情况,找到可接受的睡眠时间将减慢处理速度并将其降低到更正常的速度。

执行我们的脚本

python track.py

结果:

或者指定视频路径

python track.py --video "video\2018-11-27 18-38-15-927.mp4"

也是可以的。

完整代码:

链接:https://pan.baidu.com/s/1jvnoV_StHRTXlzK5Zvc3dw 提取码:q9bl

更多的参考:

Case Studies – Object Tracking in Video

imutils library

OpenCV Track Object Movement

Histogram of Oriented Gradients and Object Detection


---------------- The End ----------------
支持一下
Fork me on GitHub ;